/***************************************************************************
 创建者: 华磊
 开始时间: 2018.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2017.5.8 类的具体实现代码编写

 ***************************************************************************/
#include "robotengine.h"
#include <QDebug>
#include <QFile>
#include <QDomNodeList>
#include <QSettings>
#include "robotcontrol.h"
#include "messagelog.h"
#include "../ProgramEngine/programengine.h"
#include "robotbase.h"
#include "mccontrollerthread.h"

extern RobotControl* robCtl;

RobotEngine::RobotEngine(QObject *parent):
    QObject(parent)
{

    versionInfo.componentName="RobotEngine";
    versionInfo.componentVersion="V1.0";
    versionInfo.publishDate="2018.10.27";

    threadMotionEngine=NULL;
//    threadProgramEngine=NULL;
    //mcControllerInterpreter=NULL;
    programEngine=NULL;
    ioController=NULL;
    //settings = NULL;
    isManualLooseServo=false;
}

RobotEngine::~RobotEngine()
{
}
int RobotEngine::getWeldSystemInfo(struct WeldSystemInfo &weldSystemInfo){
    return programEngine->getWeldSystemInfo(weldSystemInfo);
}
int RobotEngine::changeWeldSystemInfo(struct WeldSystemInfo configIn){
    return programEngine->changeWeldSystemInfo(configIn);
}

int RobotEngine::getWeldCondition(std::vector<WeldCondition> &configListOut){

    return programEngine->getWeldCondition(configListOut);
}

int RobotEngine::changeWeldConditionConfig(struct WeldCondition &weldCondition){
    return programEngine->chanegWeldConditionConfig(weldCondition);
}

int RobotEngine::getWeldProperty(std::vector<WeldProperty> &configListOut)
{
    return programEngine->getWeldProperty(configListOut);
}

int RobotEngine::changeWeldPropertConfig(struct WeldProperty &weldProperty)
{
    return programEngine->chanegWeldPropertyConfig(weldProperty);
}

int RobotEngine::getProgramSetRunFile(QString &fileName)
{
    return programEngine->getProgramSetRunFile(fileName);
}

int RobotEngine::getEngineStatue()
{
    return programEngine->getEngineStatue();
}

int RobotEngine::setEngineStatus_fleet(STOP_COMMAND_TYPE statusIn)
{
    return programEngine->setEngineStatus_fleet(statusIn);
}

int RobotEngine::addMonitorDi_fleet(bool isOr, QVector<int> diIndex, QVector<int> diValue)
{
    return programEngine->addMonitorDi_fleet(isOr,diIndex,diValue);
}

E_PROGRAM_LOOP_RESULT RobotEngine::moveRobotArm_run(const QVector<int> &lineList,
                                                    const QVector<RobotArmMoveParameter> &pathListParaIn, int isLastPointMove)
{
      return programEngine->moveRobotArm_run(lineList,pathListParaIn,isLastPointMove);
}

E_PROGRAM_LOOP_RESULT RobotEngine::moveMultiPoint_run(const QVector<int> &lineList,
                                const QVector<LaserPathParameter> &laserPathListParaIn, int isLastPointMove)
{
    return programEngine->moveMultiPoint_run(lineList,laserPathListParaIn,isLastPointMove);
}

E_PROGRAM_LOOP_RESULT RobotEngine::moveMagnetic_run(const MaganeticPathParameter paraIn)
{
     return programEngine->moveMagnetic_run(paraIn);
}

E_PROGRAM_LOOP_RESULT RobotEngine::roller_run(const RollerParameter &paraIn)
{
    return programEngine->roller_run(paraIn);
}

E_PROGRAM_LOOP_RESULT RobotEngine::charging_run(const ChargeParameter &paraIn)
{
    return programEngine->charging_run(paraIn);
}

E_PROGRAM_LOOP_RESULT RobotEngine::liftMechanism_run(const LiftParameter &paraIn)
{
    return programEngine->liftMechanism_run(paraIn);
}

int RobotEngine::playSystemMusic(QString nameIn, int musicPlayTimes)
{
    return programEngine->playSystemMusic(nameIn,musicPlayTimes);
}

int RobotEngine::playMusic(QString musicFileName, int musicPlayTimes, int musicVolume)
{
    return programEngine->playMusic(musicFileName,musicPlayTimes,musicVolume);
}

int RobotEngine::playBarriorMusic(double barrierRatioIn)
{
    return programEngine->playBarriorMusic(barrierRatioIn);
}

int RobotEngine::playErrorMusic()
{
    return programEngine->playErrorMusic();
}

int RobotEngine::restoreNormalMusic()
{
    return programEngine->restoreNormalMusic();
}

int RobotEngine::clearAllMsg()
{
    return programEngine->clearAllMsg();
}

int RobotEngine::addCommand(UserCommandData commandIn)
{
    return programEngine->addCommand(commandIn);
}

int RobotEngine::readVersion(std::vector <ComponentVersion> &componentVersionList)
{

    componentVersionList.push_back(versionInfo);
    programEngine->readVersion(componentVersionList);
    return 1;
}

void RobotEngine::init(int startType)
{
    RegData* regData = new RegData;
    regData->Init(startType);
    RsrInfo* rsrInfo = new RsrInfo(robotInfo.robotId);

    if(NULL == ioController)
    {
        ioController = robCtl->robotsMap.value(robotInfo.robotId)->logicRobotIo;
    }
    if(NULL == threadMotionEngine)
    {
        threadMotionEngine = new McControllerThread(robotInfo.robotId,regData,ioController);
    }

    while( !threadMotionEngine->mcControllerInterpreter )
    {
        usleep(500);
    }

    if(  false==threadMotionEngine->mcControllerInterpreter->getInitialStatus() )
    {
        sleep(3);
    }

    programEngine = new ProgramEngine(robotInfo.robotId,ioController,regData,rsrInfo,startType,threadMotionEngine);

    connect( this, SIGNAL(openFile_signal(QString)) , programEngine , SLOT(openFile_clearPrivious(QString)), Qt::QueuedConnection );
    connect( this, SIGNAL(openDefaultFile_signal()) , programEngine , SLOT(openDefaultFile_clearPrivious()), Qt::QueuedConnection );
//    connect( this, SIGNAL(signal_runProgram()) , programEngine , SLOT(runProgramSlot()), Qt::QueuedConnection );
//    connect( this,SIGNAL(signal_ceaseProgram()),programEngine,SLOT(ceaseProgram()),Qt::QueuedConnection);
//    connect(this,SIGNAL(signal_resetProgram()),programEngine,SLOT(resetEngineAll()),Qt::QueuedConnection);
    connect(this,SIGNAL(signal_releaseHoldOn()),programEngine,SLOT(releaseHoldOn()),Qt::QueuedConnection);
    connect(this,SIGNAL(signal_setErrorMsgModel()),programEngine,SLOT(setErrorMsgModel()),Qt::QueuedConnection);
    connect(this,SIGNAL(signal_setStartLine(int)),programEngine,SLOT(setStartLine(int)),Qt::QueuedConnection);

    readDefaultFileSetting();
    openFile(QString::fromStdString(defaultFileName));
    setRunModel((EN_CONTROL_TYPE)externModel);

    //fleetService
//    fleetService=new FleetService(robotInfo.robotId,ioController,threadMotionEngine,programEngine);


    qDebug()<<"thr======ID:" << QThread::currentThreadId();
}

 int RobotEngine::controllerShutDown()
 {
     //todo hualei 保存其它信息
     writeExternModelToFile(programEngine->getRunModel());
     programEngine->regData->writeAllReg_toFile();
     threadMotionEngine->mcControllerInterpreter->controllerShutDown();
     return 1;
 }

int RobotEngine::setRunModel(EN_CONTROL_TYPE runModelIn)
{
    //?为什么会和openfile形成死锁　todo

    return programEngine->setRunModel_taskManager(runModelIn,isManualLooseServo);
}

int RobotEngine::getEmergencyDi(bool &emStop1,bool &emStop2)
{
    if(NULL == ioController)
    {
        return -100;
    }
    return ioController->getEmergencyDi(emStop1,emStop2);
}

int RobotEngine::getServoOnDi(bool &servoOnDi)
{
    if(NULL == ioController)
    {
        return -1;
    }
    return ioController->getServoOnDi(servoOnDi);
}

unsigned short RobotEngine::getDi_short(int shortIndex)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getDi_short(shortIndex);
}

unsigned short RobotEngine::getDo_short(int shortIndex)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getDo_short(shortIndex);
}

int RobotEngine::setDoVector(unsigned short doListIn, unsigned short doValidMask)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->setDoVector(doListIn,doValidMask);
}

bool RobotEngine::getCustomDiStatus(int index)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getDi(index);
}

bool RobotEngine::getSystemDiStatus(int index)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getSi(index);
}

bool RobotEngine::getSystemDoStatus(int index)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getSo(index);
}

int RobotEngine::getCustomDoStatus(int index)
{
    if(NULL == ioController)
    {
        return false;
    }
    return ioController->getDo(index);
}

int RobotEngine::setSystemDo(int index,bool val)
{
    if(NULL == ioController)
    {
        return -1;
    }
    return ioController->setSo(index,val);
}

int RobotEngine::setCustomDo(int index,bool val)
{
    if(NULL == ioController)
    {
        return -1;
    }
    return ioController->setDo(index,val);
}

int RobotEngine::setAo(int index, double valIn)
{
    if(NULL == ioController)
    {
        return -1;
    }
    return ioController->setAo(index,valIn);
}

int RobotEngine::setCustomDi(int index, bool val)
{
    if(NULL == ioController)
    {
        return -1;
    }
    return ioController->setDi(index,val);
}

bool RobotEngine::readDefaultFileSetting( )
{
    std::string filePath = robotInfo.robotFileAddress + "config/defaultProgram.ini";
    QString defaultFileNameStr = QString::fromStdString(filePath);

    if( !QFile::exists(defaultFileNameStr) )
    {
        // MessageLog::addMessage(" ");
        //消息预留
        //获取默认程序文件失败：文件不存在或路径错误
        qDebug()<< "获取默认程序文件失败：文件不存在或路径错误"<<defaultFileNameStr ;
        return false;
    }


    QSettings settings(defaultFileNameStr,QSettings::IniFormat);
    settings.setIniCodec("UTF-8");
    QString strConfigValue = settings.value( "defaultProgram/name").toString();
    defaultFileName = strConfigValue.toStdString();

    QString externModelStr = settings.value("externModel/externFlag").toString();
    externModel = externModelStr.toInt();


    filePath = robotInfo.robotFileAddress + "program/" + defaultFileName;

    std::cout << "获取默认程序文件 ：" << filePath << std::endl;
    defaultFile = QString::fromStdString(filePath);
    if(QFile::exists( defaultFile ))
    {
        return true;
    }
    else
    {
        //消息预留
        //获取默认程序文件失败：文件不存在或路径错误
        //MessageLog::getInstance()->addMessage(ENUM_MSG_WARNING,"RobotEngine","RobotEngine",1004,robotInfo.robotId);
        return false;
    }
}
int RobotEngine::writeDefaultFileSetting(std::string inFileName)
{
    std::string filePath = robotInfo.robotFileAddress + "config/defaultProgram.ini";
    QString defaultFileNameStr = QString::fromStdString(filePath);

    if( !QFile::exists(defaultFileNameStr) )
    {
        // MessageLog::addMessage(" ");
        //消息预留
        //获取默认程序文件失败：文件不存在或路径错误
        qDebug()<< "获取默认程序文件失败：文件不存在或路径错误"<<defaultFileNameStr ;
        return -1;
    }
    QSettings settings(defaultFileNameStr,QSettings::IniFormat);
    settings.setIniCodec("UTF-8");
    settings.setValue("/defaultProgram/name", inFileName.data());

    return 1;
}
int RobotEngine::getRobotBasicStatus()
{
//    return programEngine->programMcController->mcControllerInterpreter->getStatus();
    return programEngine->getProgramEngineStatus();//by hualei
}

bool RobotEngine::readRobotInfoXml( QString xmlfile )
{
    bool ok=openXml( xmlfile, QFile::ReadOnly | QFile::Text );
    if(!ok)
    {
        //消息预留
        //打开ｘｍｌ文件失败
        qDebug()<< "ERROR: openXml :RobotEngine::readRobotInfoXml"  << xmlfile;
        return false;
    }

    QDomNode  robNode =  m_root ;
    readXml( findSubNode( robNode, "robotName", ok ), robotInfo.robotName );
    readXml( findSubNode( robNode, "robotSetting", ok ), robotInfo.robotSetting );
    readXml( findSubNode( robNode, "ioMapXML", ok ), robotInfo.ioMapXML );

    readXml( findSubNode( robNode, "robotMotorCount", ok ), robotInfo.robotMotorCount );
    readXml( findSubNode( robNode, "extMotorCount", ok ), robotInfo.extMotorCount );


    QString pic;
    QString robotSpecification;

    readXml( findSubNode( robNode, "robotSpecification", ok ), robotSpecification );
    readXml( findSubNode( robNode, "robotType", ok ),  robotInfo.robotType  );
    readXml( findSubNode( robNode, "robotPicture", ok ), pic );

    robotInfo.robotSpecification = robotSpecification.toStdString();	//机器人规格
    QString tmpFilePath=D_TCRCONTROLLER_DATA_PATH;
    robotInfo.robotFileAddress = QString(tmpFilePath+ROBOT_COMMON_NAME + QString::number( robotInfo.robotId ))
            .toStdString() + "/";	//机器人所在的文件路径
<<<<<<< HEAD
//    robotInfo.robotPictureAddress =  robotInfo.robotFileAddress +QString("config/").toStdString()+ pic.toStdString();//机器人所在的图片路径
    robotInfo.robotPictureAddress = pic.toStdString();//机器人所在的图片路径
=======
    robotInfo.robotPictureAddress =  robotInfo.robotFileAddress +QString("config/").toStdString()+ pic.toStdString();//机器人所在的图片路径
>>>>>>> origin/master

    if(!ok)
    {
        //消息预留
        //获取机器人信息失败
        qDebug()<<"Error : read robot infomation !RobotEngine::readRobotInfoXml"  ;
    }

    int axisCount= robotInfo.robotMotorCount + robotInfo.extMotorCount;
    robotInfo.motorAlias.resize( axisCount );
    for(int j=0;j< axisCount; j++)
    {
        if(j<robotInfo.robotMotorCount)
        {
            ok=readXml( findSubNode( robNode, QString("robotNodeAlias%1").arg(j+1), ok )
                        ,robotInfo.motorAlias[j]  );
        }else{
            ok=readXml( findSubNode( robNode, QString("extNodeAlias%1").arg(j-robotInfo.robotMotorCount+1), ok )
                        ,robotInfo.motorAlias[j]  );
        }
        if(!ok){
            qDebug()<<"error: RobotEngine::readRobotInfoXml"<<__FILE__<< __LINE__  << j ;
        }
    }

    closeXml();

    return ok?true:false;

}

int RobotEngine::writeExternModelToFile(int externModel)
{
    std::string filePath = robotInfo.robotFileAddress + "config/defaultProgram.ini";
    QString defaultFileNameStr = QString::fromStdString(filePath);

    if( !QFile::exists(defaultFileNameStr) )
    {
        // MessageLog::addMessage(" ");
        //消息预留
        //获取默认程序文件失败：文件不存在或路径错误
        qDebug()<< "获取默认程序文件失败：文件不存在或路径错误"<<defaultFileNameStr ;
        return -1;
    }


    QString strConfigGroup = "";
    QString strConfigKey = "";


    QSettings settings(defaultFileNameStr,QSettings::IniFormat);
    settings.setIniCodec("UTF-8");

    strConfigGroup = "externModel";
    settings.beginGroup(strConfigGroup);

    strConfigKey = "externFlag";
    settings.setValue(strConfigKey,QVariant(externModel));
    settings.endGroup();


}


int RobotEngine::openFile( QString strFilePath )
{
    emit openFile_signal( strFilePath ); //解释文件太耗时，需异步处理
    return 1;
}

int RobotEngine::openDefaultFile()
{
    emit openDefaultFile_signal(  ); //解释文件太耗时，需异步处理
    return 1;
}

 int RobotEngine::runProgram( )
 {
     return programEngine->runProgram();
//     emit signal_runProgram();
 }

 int RobotEngine::ceaseProgram()
 {

     return programEngine->ceaseProgram();

 }

 int RobotEngine::quickStop()
 {
    programEngine->quickStop();
 }

 int RobotEngine::resetProgram()
 {

     return programEngine->resetEngineAll();

//     QCoreApplication::processEvents();
//     sleep(1);
//     programEngine->resetEngineAll();todo

//     emit signal_resetProgram();

     //hualei 用信号会被阻塞
//     programEngine->resetProgram();
//    #endif
 }

 void RobotEngine::releaseHoldOn()
 {
     emit signal_releaseHoldOn();
 }

 void RobotEngine::setErrorMsgModel()
 {
     emit signal_setErrorMsgModel();
 }

 void RobotEngine::setStartLine(int startLine)
 {
     emit signal_setStartLine(startLine);
 }

 int RobotEngine::readConfigFile(QString configFilePathIn)
 {
     qDebug()<<"RobotEngine::readConfigFile,fileName="<<configFilePathIn;
     QSettings settings(configFilePathIn, QSettings::IniFormat);

     QString strConfigKey;

     strConfigKey= "ModelInfo/isManualLooseServo";
     if(false==settings.contains(strConfigKey))
     {
         qDebug()<<"error,,,,,RobotEngine loose parameter.ModelInfo/isManualLooseServo";
//         addMsg(ENUM_MSG_ERROR, "MotionServer", "RobotAttribute" , 5220, robotId);
         return -1;
     }
     isManualLooseServo = settings.value(strConfigKey).toBool();
     return 1;
 }

// void RobotEngine::setTimerReg(int timerNum, int changeStatus)
// {
//     emit signal_setTimerReg(timerNum,changeStatus);
// }






